﻿using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Linq;
using System.Text;
using BTCe.Constant;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;

namespace BTCe.Common
{
    public class BTCeAccessInfo
    {
        private eBTCeServer _Server;
        private string _BaseURL;
        private string _UserID;
        private string _UserPWD;
        private string _ClientID;
        private string _ClientSecret;
        private string _AccessToken;
        private string _token_type;
        private string _RefreshToken;
        private int _ExpiredTime;
        private int _nonce;
        private bool _bLogin;
        
        public BTCeAccessInfo()
        {
            SetServer(eBTCeServer.TEST);
        }

        public BTCeAccessInfo(eBTCeServer eServer)
        {
            SetServer(eServer);
        }

        private void initialized()
        {
            _bLogin = false;
            _nonce = 1;
        }

        public void SetServer(eBTCeServer eServer)
        {
            _Server = eServer;
            //hyperioner 키

            if (eServer == eBTCeServer.RUNNING)
            {
                _BaseURL = "https://btc-e.com";
                _ClientID = "C90TUF4U-4JSG5LVA-X9UCDAHK-XCKV4TK4-G6AWYY2Z";
                _ClientSecret = "74b0aa27e740cd06e4f19adebdca065f66cfab27dc02a0316c647b71e6afe466";
                _UserID = "hyperioner@gmail.com";
                _UserPWD = "overdrive@1";
            }
            else
            {
                _BaseURL = "https://btc-e.com";
                _ClientID = "C90TUF4U-4JSG5LVA-X9UCDAHK-XCKV4TK4-G6AWYY2Z";
                _ClientSecret = "74b0aa27e740cd06e4f19adebdca065f66cfab27dc02a0316c647b71e6afe466";
                _UserID = "hyperioner@gmail.com";
                _UserPWD = "overdrive@1";
            }

            initializedNonce();
        }

        private void initializedNonce()
        {
            int iNew;

            iNew = (int)(DateTime.Now - DateTime.Parse("2015-03-01")).TotalSeconds;

            _nonce = iNew;
        }

        /// <summary>
        /// Gets the base URL.
        /// </summary>
        /// <returns></returns>
        public string GetBaseURL()
        {
            return _BaseURL;
        }

        /// <summary>
        /// Gets the client identifier.
        /// </summary>
        /// <returns></returns>
        public string GetClientID()
        {
            return _ClientID;
        }

        /// <summary>
        /// Gets the client secret.
        /// </summary>
        /// <returns></returns>
        public string GetClientSecret()
        {
           return _ClientSecret;
        }


        /// <summary>
        /// Gets the user identifier.
        /// </summary>
        /// <returns></returns>
        public string GetUserID()
        {
            return _UserID;
        }

        /// <summary>
        /// Gets the user password.
        /// </summary>
        /// <returns></returns>
        public string GetUserPWD()
        {
            return _UserPWD;
        }

        /// <summary>
        /// Gets the access token.
        /// </summary>
        /// <returns></returns>
        public string GetAccessToken()
        {
            return this._AccessToken;
        }

        /// <summary>
        /// Sets the access token.
        /// </summary>
        /// <param name="strAccessToken">The string access token.</param>
        public void SetAccessToken(String strAccessToken)
        {
            this._AccessToken = strAccessToken;
        }

        /// <summary>
        /// Gets the refresh token.
        /// </summary>
        /// <returns></returns>
        public string GetRefreshToken()
        {
            return this._RefreshToken;
        }

        /// <summary>
        /// Sets the refresh token.
        /// </summary>
        /// <param name="strRefreshToken">The string refresh token.</param>
        public void SetRefreshToken(String strRefreshToken)
        {
            this._RefreshToken = strRefreshToken;
        }

        /// <summary>
        /// Expireds the time.
        /// </summary>
        /// <returns></returns>
        public int ExpiredTime()
        {
            return this._ExpiredTime;
        }

        /// <summary>
        /// Sets the expired time.
        /// </summary>
        /// <param name="iExpiredTime">The i expired time.</param>
        public void SetExpiredTime(int iExpiredTime)
        {
            this._ExpiredTime = iExpiredTime;
        }

        /// <summary>
        /// Gets the nonce.
        /// </summary>
        /// <returns></returns>
        public int GetNonce()
        {
            this._nonce = this._nonce + 1;

            return this._nonce;
        }

        /// <summary>
        /// Sets the nonce.
        /// </summary>
        /// <param name="iNonce">The i nonce.</param>
        public void SetNonce(int iNonce)
        {
            this._nonce = iNonce;
        }

        /// <summary>
        /// Gets the type of the token.
        /// </summary>
        /// <returns></returns>
        public String GetTokenType()
        {
            return this._token_type;
        }

        /// <summary>
        /// Sets the type of the token.
        /// </summary>
        /// <param name="strTokenType">Type of the string token.</param>
        public void SetTokenType(String strTokenType)
        {
            this._token_type = strTokenType;
        }

        /// <summary>
        /// Sets the authrization.
        /// </summary>
        /// <param name="strTokenType">Type of the string token.</param>
        /// <param name="strAccessToken">The string access token.</param>
        /// <param name="iExpiredTime">The i expired time.</param>
        /// <param name="strRefreshToken">The string refresh token.</param>
        public void SetAuthrization(String strTokenType, String strAccessToken, int iExpiredTime, String strRefreshToken)
        {
            SetTokenType(strTokenType);

            SetAccessToken(strAccessToken);

            SetExpiredTime(iExpiredTime);

            SetRefreshToken(strRefreshToken);
        }

        public String GetAuthorizationInfo()
        {
            string strReturn = "";

            //사용자 정보를 가져온다.
            Dictionary<String, String> dicURLParameter = new Dictionary<string, string>();
            dicURLParameter.Add("sign", GetClientID());
            dicURLParameter.Add("client_secret", GetClientSecret());
            dicURLParameter.Add("username", GetUserID());
            dicURLParameter.Add("password", GetUserPWD());
            dicURLParameter.Add("grant_type","password");

            strReturn = CommonFunction.ConvertURLParameter(dicURLParameter);

            return strReturn;
        }

        public String GetRefreshTokenInfo()
        {
            string strReturn = "";
            
            //사용자 정보를 가져온다.
            Dictionary<String, String> dicURLParameter = new Dictionary<string, string>();
            dicURLParameter.Add("client_id", GetClientID());
            dicURLParameter.Add("client_secret", GetClientSecret());
            dicURLParameter.Add("refresh_token", GetRefreshToken());
            dicURLParameter.Add("grant_type", "refresh_token");

            strReturn = CommonFunction.ConvertURLParameter(dicURLParameter);

            return strReturn;
        }


        public string GetAuthorization(string strBaseURL, string strParameters)
        {
            string strReturn = "";

            strReturn = Communication.GetRequestData(strBaseURL + BTCeURL.URL_ACCESS_TOKEN, strParameters, GetHttpHeaderAPI(""));

            return strReturn;
        }

        public string RefreshToken(string strBaseURL, string strParameters)
        {
            string strReturn = "";

            //strReturn = Communication.GetRequestData(strBaseURL + BTCeURL.URL_ACCESS_TOKEN, strParameters);

            return strReturn;
        }


        /// <summary>
        /// Longins this instance.
        /// </summary>
        /// <returns></returns>
        public bool Login()
        {
            bool bReturn;

            bReturn = false;

            //Access Info 설정
            string strParameters = GetAuthorizationInfo();

            //데이터를 받아온다.
            string strData = GetAuthorization(GetBaseURL(), strParameters);

            //데이터가 없는 경우 반환한다.
            if (strData.Length == 0)
                return bReturn;

            //Value를 입력한다.
            string strAccessToken;
            string strRefreshToken;
            string strTokenType;
            int iExpiredTime;

            //접속 정보를 추출한다.
            JObject objData = JObject.Parse(strData);
            strAccessToken = objData["access_token"].ToString();
            strRefreshToken = objData["refresh_token"].ToString();
            strTokenType = objData["token_type"].ToString();
            iExpiredTime = (int)objData["expires_in"];

            //접속 정보를 입력한다.
            SetAccessToken(strAccessToken);
            SetRefreshToken(strRefreshToken);
            SetExpiredTime(iExpiredTime);
            SetTokenType(strTokenType);

            _bLogin = true;

            bReturn = true;

            return bReturn;
        }

        public bool IsLogin()
        {
            if (GetClientID().Length == 0 || GetClientSecret().Length == 0)
                return false;
            
            return true;
        }

        /// <summary>
        /// Refreshes the token.
        /// </summary>
        /// <returns></returns>
        public bool RefreshToken()
        {
            bool bReturn;

            bReturn = false;

            //Access Info 설정
            string strParameters = GetRefreshTokenInfo();

            //데이터를 받아온다.
            string strData = RefreshToken(GetBaseURL(), strParameters);

            //데이터가 없는 경우 반환한다.
            if (strData.Length == 0)
                return bReturn;

            //Value를 입력한다.
            string strAccessToken;
            string strRefreshToken;
            string strTokenType;
            int iExpiredTime;

            //접속 정보를 추출한다.
            JObject objData = JObject.Parse(strData);
            strAccessToken = objData["access_token"].ToString();
            strRefreshToken = objData["refresh_token"].ToString();
            strTokenType = objData["token_type"].ToString();
            iExpiredTime = (int)objData["expires_in"];

            //접속 정보를 입력한다.
            SetAccessToken(strAccessToken);
            SetRefreshToken(strRefreshToken);
            SetExpiredTime(iExpiredTime);
            SetTokenType(strTokenType);

            bReturn = true;

            return bReturn;
        }

        public void Print()
        {
            Console.WriteLine("Base URL : " + _BaseURL );
            Console.WriteLine("Client ID : " + _ClientID );
            Console.WriteLine("Client Secret : " + _ClientSecret );
            Console.WriteLine("ID : " + _UserID );
            Console.WriteLine("Password : " + _UserPWD );
            Console.WriteLine("Access Token : " + _AccessToken );
            Console.WriteLine("Token Type : " + _token_type );
            Console.WriteLine("Refresh Token : " + _RefreshToken );
            Console.WriteLine("Expired Time : " + _ExpiredTime.ToString() );
            Console.WriteLine("Login : " + _bLogin.ToString() );
            
        }

        public Dictionary<string, string> GetURLParameterAccessKey()
        {
            if (!IsLogin())
                return null;

            Dictionary<string, string> dicURLParameter = new Dictionary<string, string>();
            //dicURLParameter.Add("access_token", GetAccessToken());
            dicURLParameter.Add("nonce", GetNonce().ToString());

            return dicURLParameter;
        }

        public Dictionary<string, string> GetHttpHeaderAPI(string strURLParameter)
        {
            Dictionary<string, string> dicHeader = new Dictionary<string, string>();

            dicHeader.Add("Key", GetClientID());
            dicHeader.Add("Sign", GetHttpSign(strURLParameter));

            return dicHeader;
        }

        public string GetHttpSign(string strURLParameter)
        {
            string strReturn = "";

            HMACSHA512 oEncrypt = CommonFunction.HMACSHA512Encript(GetClientSecret());
            strReturn = BitConverter.ToString(oEncrypt.ComputeHash(Encoding.ASCII.GetBytes(strURLParameter))).Replace("-", "").ToLower();

            return strReturn;
        }
    }
}
